﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Data;

using ExchangeRateService.Command;
using ExchangeRateService.DataAccess;
using ExchangeRateService.Model;

namespace ExchangeRateService.ViewModel
{
	/// <summary>
	/// Description of MainWindowViewModel.
	/// </summary>
	public class MainWindowViewModel : WorkspaceViewModel
	{
		#region Fields
		
		Boolean _firstLoad;
                
        ReadOnlyCollection<CommandViewModel> _commands;
        readonly CurrencyRepository _repository;
        ObservableCollection<WorkspaceViewModel> _workspaces;

        #endregion // Fields
        
		public MainWindowViewModel(String datafile)
		{
			base.DisplayName = Properties.StringResource.MAINWINDOWVIEWMODEL_DISPLAYNAME;
			
			_repository = new CurrencyRepository(datafile);
		}
		
		#region Properties
		
		public Boolean IsFirstLoad
		{
			get { return _firstLoad; }
			set
			{
				if (_firstLoad == value) return;
				_firstLoad = value;
				OnPropertyChanged("IsFirstLoad");
			}
		}
		
		#endregion
		
		#region Commands

        /// <summary>
        /// Returns a read-only list of commands 
        /// that the UI can display and execute.
        /// </summary>
        public ReadOnlyCollection<CommandViewModel> Commands
        {
            get
            {
                if (_commands == null)
                {
                    List<CommandViewModel> cmds = this.CreateCommands();
                    _commands = new ReadOnlyCollection<CommandViewModel>(cmds);
                }
                return _commands;
            }
        }

        List<CommandViewModel> CreateCommands()
        {
            return new List<CommandViewModel>
            {
            	new CommandViewModel(Properties.StringResource.SHOW_RATES_SUPPLEMENT,
            	                     new RelayCommand(param => this.ExecuteShowRatesSupplement())),
            	new CommandViewModel(Properties.StringResource.SHOW_CURRENCY_EXCHANGE,
            	                     new RelayCommand(param => this.ExecuteShowCurrencyExchange()))
            };
        }

        #endregion // Commands
        
        #region Workspaces

        /// <summary>
        /// Returns the collection of available workspaces to display.
        /// A 'workspace' is a ViewModel that can request to be closed.
        /// </summary>
        public ObservableCollection<WorkspaceViewModel> Workspaces
        {
            get
            {
                if (_workspaces == null)
                {
                    _workspaces = new ObservableCollection<WorkspaceViewModel>();
                    _workspaces.CollectionChanged += this.Workspaces_CollectionChanged;
                }
                return _workspaces;
            }
        }

        void Workspaces_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.NewItems)
                    workspace.RequestClose += this.Workspace_RequestClose;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.OldItems)
                    workspace.RequestClose -= this.Workspace_RequestClose;
        }

        void Workspace_RequestClose(object sender, EventArgs e)
        {
            WorkspaceViewModel workspace = sender as WorkspaceViewModel;
            workspace.Dispose();
            this.Workspaces.Remove(workspace);
        }

        #endregion // Workspaces
        
        #region Methods
        
        void ExecuteShowRatesSupplement()
        {
        	RateSupplementViewModel workspace =
                this.Workspaces.FirstOrDefault(vm => vm is RateSupplementViewModel)
                as RateSupplementViewModel;

            if (workspace == null)
            {
                workspace = new RateSupplementViewModel(_repository);
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }
        
        void ExecuteShowCurrencyExchange()
        {
        	CurrencyViewModel workspace =
        		this.Workspaces.FirstOrDefault(vmm => vmm is CurrencyViewModel)
        		as CurrencyViewModel;
        		
        	if (workspace == null)
        	{
        		Currency dummy = Currency.CreateNewCurrency();
        	
        		workspace = new CurrencyViewModel(dummy, _repository);

        		this.Workspaces.Add(workspace);
        	}
        	
        	this.SetActiveWorkspace(workspace);
        }
        
        void SetActiveWorkspace(WorkspaceViewModel workspace)
        {
            Debug.Assert(this.Workspaces.Contains(workspace));

            ICollectionView collectionView = CollectionViewSource.GetDefaultView(this.Workspaces);
            if (collectionView != null)
                collectionView.MoveCurrentTo(workspace);
        }
        
        #endregion // Methods
	}
}
